package com.example.java_gobang.api;

import com.example.java_gobang.game.MatchRequest;
import com.example.java_gobang.game.MatchResponse;
import com.example.java_gobang.game.Matcher;
import com.example.java_gobang.game.OnlineUserManager;
import com.example.java_gobang.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

//这个类来处理匹配功能的websocket请求
@Component
public class MatchAPI extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private Matcher matcher;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线, 加入到OnlineUserManager中
        // 1. 先获取到当前用户的身份信息(谁在游戏大厅中,建立连接)
        //前面已经把Http里的session在注册Websocket的时候放入,所以获取的是HttpSession里的session
        //此时就可以在 WebSocket中把之前HttpSession 里存的User对象拿到

        try {
            User user =(User)session.getAttributes().get("user");  //此次拿到的user有可能为空

            // 2. 先判定当前用户是否已经登录过(已经是在线状态), 如果是已经在线, 就不该继续进行后续逻辑.
            if (onlineUserManager.getFromGameHall(user.getUserId()) != null
                    || onlineUserManager.getFromGameRoom(user.getUserId()) != null) {
                // 当前用户已经登录了!!
                // 针对这个情况要告知客户端, 你这里重复登录了.
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setReason("当前禁止多开!");
                response.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                // 此处直接关闭有些太激进了, 还是返回一个特殊的 message , 供客户端来进行判定, 由客户端负责进行处理
                // session.close();
                return;
            }

            //3. 拿到身份信息之后就可以把玩家设置成在线状态
            onlineUserManager.enterGameHall(user.getUserId(), session);
            System.out.println("玩家: "+user.getUserName()+"进入游戏大厅了");

        }catch (NullPointerException e){
            System.out.println("[MatchAPI][afterConnectionEstablished] 当前用户未登录");
            /*e.printStackTrace();  //出现空指针异常,说明用户未登录
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("您尚未登录!不能进行后续匹配功能");

            //先通过objectMapper把response转成JSON字符串,然后包装上一层TextMessage,再进行传输
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));  //TextMessage表示一个文本格式的websocket数据包*/
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //实现处理开始匹配请求和处理停止匹配请求
        User user = (User)session.getAttributes().get("user");  //拿到用户的身份信息

        //获取客户端给服务器发送的数据
        String payload = message.getPayload();

        //当前这个数据载荷是一个JSON格式的字符串,需要把它转换成Java对象,MatchRequest
        MatchRequest request = objectMapper.readValue(payload, MatchRequest.class);
        MatchResponse response = new MatchResponse();
        if (request.getMessage().equals("startMatch")) {
            //进入匹配队列
            matcher.add(user);

            //把玩家信息放入到匹配队列之后,就可以返回一个响应给客户端
            response.setOk(true);
            response.setMessage("startMatch");
        } else if (request.getMessage().equals("stopMatch")) {
            //退出匹配队列
            matcher.remove(user);

            //移除之后,就可以返回一个响应给客户端
            response.setOk(true);
            response.setMessage("stopMatch");
        }else {
            //非法情况
            response.setOk(false);
            response.setReason("非法的匹配请求");
        }
        //服务器处理匹配请求的时候,要立即返回一个websocket响应
        String jsonString = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(jsonString));

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try {
            //玩家下线, 从OnlineUserManager删除
            User user = (User)session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId()); //获取存储的session

            if (tmpSession == session) {  //session是连接中的会话  tmpSession是之前存的会话
                onlineUserManager.exitGameHall(user.getUserId());  //下线操作
            }

            matcher.remove(user);  //连接异常退出关闭也要从队列中去除
        }catch (NullPointerException e) {
            System.out.println("[MatchAPI][handleTransportError] 当前用户未登录");
            /*e.printStackTrace();
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("您尚未登录!不能进行后续匹配功能");

            //先通过objectMapper把response转成JSON字符串,然后包装上一层TextMessage,再进行传输
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));*/  //TextMessage表示一个文本格式的websocket数据包
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            //玩家下线, 从OnlineUserManager删除
            User user = (User)session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());

            if (tmpSession == session) {  //session是连接中的会话  tmpSession是之前存的会话
                onlineUserManager.exitGameHall(user.getUserId());  //下线操作
            }

            matcher.remove(user);  //连接异常退出关闭也要从队列中去除
        }catch (NullPointerException e) {
            //e.printStackTrace();
            System.out.println("[MatchAPI][afterConnectionClosed] 当前用户未登录");
            /*MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("您尚未登录!不能进行后续匹配功能");*/

            /*//先通过objectMapper把response转成JSON字符串,然后包装上一层TextMessage,再进行传输
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response))); */ //TextMessage表示一个文本格式的websocket数据包
        }

    }
}
